import java.net.InetAddress;

public class TCPPortScanner {

	public final static int NUMBEROFTHREADS = 1024; // Less than 65535

	int startPort, endPort; 			// Port range
	OpenPorts openPorts;				// Array maintaining all of the open ports of the target
	InetAddress host;  					// Target IP address/hostname 
	TCPPortScannerThread[] threads = new TCPPortScannerThread[NUMBEROFTHREADS];

	/**
	 * Constructor of the class TCPPortScanner. Initializes all the private variables needed.
	 * @param host
	 * 		The target
	 * @param startPort
	 * 		The start of the port range to look up to
	 * @param endPort
	 * 		The end of the port range to loop up to
	 */
	public TCPPortScanner(InetAddress host, int startPort, int endPort) {
		this.startPort = startPort;
		this.endPort = (endPort > 65535) ? 65535 : endPort;
		this.host = host;

		// Initializing all the elements of openPorts with 0
		for(int i=0; i < 65535; i++) {
			OpenPorts.getInstance().set(i, false);
		} 
	}

	/**
	 * Constructor of the class TCPPortScanner. Initializes all the private variables needed.
	 * @param host
	 * 		The target
	 */
	public TCPPortScanner(InetAddress host) {
		this(host, 0, 1024);
	}

	/**
	 * Constructor of the class TCPPortScanner. Initializes all the private variables needed.
	 * @param host
	 * 		The target
	 * @param endPoint
	 * 		The end of the port range to loop up to
	 */
	public TCPPortScanner(InetAddress host, int endPoint) {
		this(host, 0, endPoint);
	}

	/**
	 * Method that runs the port scanning by creating NUMBEROFTHREADS threads which will scan a specified range of ports
	 */
	public void runPortScanning() {
		System.out.println("Scanning ports from "+startPort+" to "+endPort + " on host " + host.toString());
		// Initialize all the threads
		for(int i = 0; i < NUMBEROFTHREADS; i++) {
			int numberOfPorts = (endPort-startPort)/NUMBEROFTHREADS;
			int start = startPort + (i*numberOfPorts);
			int end = (i == NUMBEROFTHREADS-1) ? endPort : startPort + ((i+1)*numberOfPorts)-1;
			
			//System.out.println("Thread "+i+": "+"; start: "+start+"; end: "+end);
			threads[i] = new TCPPortScannerThread(host, start, end);
			threads[i].start();
		}
		
		System.out.print("Processing...\n");
		for (int i = 0; i < NUMBEROFTHREADS; i++) {
			try {
				threads[i].join();
			}
			catch (InterruptedException e) {
				System.out.print("Join interrupted\n");
			}
		}
		
		//System.out.println("All threads finished");
	}	
}
